package org.jsola.hr.service.impl;

import org.apache.commons.lang3.StringUtils;
import org.jsola.common.DateKit;
import org.jsola.core.Page;
import org.jsola.core.entity.BaseDO;
import org.jsola.hr.common.ExampleKit;
import org.jsola.hr.common.HrLogKit;
import org.jsola.hr.constant.AttendStatus;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.dao.IAttendPunchRecordDAO;
import org.jsola.hr.dao.IAttendanceDedDAO;
import org.jsola.hr.dao.IAttendanceDedItemDAO;
import org.jsola.hr.dao.IAttendanceMonthlyDAO;
import org.jsola.hr.dto.ApplyToProgEmpeeInfoDTO;
import org.jsola.hr.dto.AttendanceDedAddDTO;
import org.jsola.hr.dto.AttendanceDedUpdateDTO;
import org.jsola.hr.dto.AttendanceMonthlyAddDTO;
import org.jsola.hr.entity.*;
import org.jsola.hr.query.AttendanceDedQuery;
import org.jsola.hr.service.IApplyToProgService;
import org.jsola.hr.service.IAttendanceDedItemService;
import org.jsola.hr.service.IAttendanceDedService;
import org.jsola.hr.service.IEmpInfoService;
import org.jsola.hr.vo.AttendanceDedListVO;
import org.jsola.hr.vo.AttendanceDedVO;
import org.jsola.user.core.TokenUser;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static java.math.BigDecimal.ROUND_HALF_DOWN;

/**
 * @author zhr
 */
@Service("hrAttendanceDedServiceImpl")
public class AttendanceDedServiceImpl implements IAttendanceDedService {

    @Autowired
    private IAttendanceDedDAO attendanceDedDAO;

    @Autowired
    private IAttendPunchRecordDAO attendPunchRecordDAO;

    @Autowired
    private IAttendanceMonthlyDAO attendanceMonthlyDao;

    @Autowired
    private IEmpInfoService empInfoService;

    @Autowired
    private IAttendanceDedItemService attendanceDedItemService;

    @Autowired
    private IApplyToProgService applyToProgService;

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public AttendanceDedVO save(AttendanceDedAddDTO attendanceDedAddDTO, TokenUser tokenUser) {
        // 转DO
        AttendanceDedDO attendanceDedDO = attendanceDedAddDTO.to(AttendanceDedDO.class);
        // 保存
        attendanceDedDO = save(attendanceDedDO, tokenUser.getSiteId(), tokenUser.getUserId());
        HrLogKit.logForSave("新增考勤扣款设置", "saveAttendanceDed", attendanceDedDO.getId(), tokenUser);
        return attendanceDedDO.to(AttendanceDedVO.class);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int update(AttendanceDedUpdateDTO attendanceDedUpdateDTO, TokenUser tokenUser) {
        //转DO
        AttendanceDedDO attendanceDedDO = attendanceDedUpdateDTO.to(AttendanceDedDO.class);
        HrLogKit.logForUpdate("修改考勤扣款设置", "updateAttendanceDed", attendanceDedDO.getId(), tokenUser);
        //根据主键更新，只更新非null值
        return updateByIdSelective(attendanceDedDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteByIds(TokenUser tokenUser, String... attendanceDedIds) {
        HrLogKit.logForDelete("批量删除考勤扣款设置", "deleteAttendanceDedByIds", Arrays.toString(attendanceDedIds), tokenUser);
        return logicalDeleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(), (Object[]) attendanceDedIds);
    }


    @Override
    public AttendanceDedVO selectById(String attendanceDedId, String siteId) {
        AttendanceDedDO attendanceDedDO = selectDOById(attendanceDedId, siteId);
        if (attendanceDedDO == null) {
            return null;
        }
        return attendanceDedDO.to(AttendanceDedVO.class);
    }

    @Override
    public List<AttendanceDedListVO> select(AttendanceDedQuery attendanceDedQuery, String siteId) {
        List<AttendanceDedDO> attendanceDedDOList = selectDO(attendanceDedQuery, siteId);
        if (CollectionUtils.isEmpty(attendanceDedDOList)) {
            return attendanceDedDOList == null ? null : new ArrayList<>();
        }
        return attendanceDedDOList.stream()
                .map(attendanceDedDO -> attendanceDedDO.to(AttendanceDedListVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public int selectCount(AttendanceDedQuery attendanceDedQuery, String siteId) {
        Example example = buildExample(attendanceDedQuery, siteId);
        return attendanceDedDAO.selectCountByExample(example);
    }

    @Override
    public Page<AttendanceDedListVO> selectPage(AttendanceDedQuery attendanceDedQuery, String siteId) {
        Example example = buildExample(attendanceDedQuery, siteId);
        Page<AttendanceDedDO> page = attendanceDedDAO.selectPageByExample(example,
                attendanceDedQuery.getPageNo(),
                attendanceDedQuery.getPageSize());

        return page.to(AttendanceDedListVO.class);
    }

    @Override
    public AttendanceDedDO selectDOById(String attendanceDedId, String siteId) {
        return listById(attendanceDedId, siteId);
    }

    @Override
    public List<AttendanceDedDO> selectDO(AttendanceDedQuery attendanceDedQuery, String siteId) {
        Example example = buildExample(attendanceDedQuery, siteId);
        return attendanceDedDAO.selectByExample(example);
    }


    /**
     * 根据查询参数，构建example
     *
     * @param attendanceDedQuery 查询参数
     * @param siteId             所属站点id
     * @return example
     */
    private Example buildExample(AttendanceDedQuery attendanceDedQuery, String siteId) {
        Example example = new Example(AttendanceDedDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        if (attendanceDedQuery.getProgrammeId() != null) {
            example.and().andLike("programmeId", "%" + attendanceDedQuery.getProgrammeId() + "%");
        }
        if (attendanceDedQuery.getDedType() != null) {
            example.and().andEqualTo("dedType", attendanceDedQuery.getDedType());
        }
        if (attendanceDedQuery.getName() != null) {
            example.and().andLike("name", "%" + attendanceDedQuery.getName() + "%");
        }
        if (attendanceDedQuery.getType() != null) {
            example.and().andEqualTo("type", attendanceDedQuery.getType());
        }
        if (attendanceDedQuery.getAmountMinute() != null) {
            example.and().andEqualTo("amountMinute", attendanceDedQuery.getAmountMinute());
        }
        if (attendanceDedQuery.getAmountAbsenteeism() != null) {
            example.and().andEqualTo("amountAbsenteeism", attendanceDedQuery.getAmountAbsenteeism());
        }
        if (attendanceDedQuery.getOverallRange() != null) {
            example.and().andLike("overallRange", "%" + attendanceDedQuery.getOverallRange() + "%");
        }
        if (attendanceDedQuery.getStatus() != null) {
            example.and().andEqualTo("status", attendanceDedQuery.getStatus());
        }
        if (attendanceDedQuery.getCompanyId() != null) {
            example.and().andEqualTo("companyId", attendanceDedQuery.getCompanyId());
        }
        if (attendanceDedQuery.getGmtCreateStart() != null &&
                attendanceDedQuery.getGmtCreateEnd() != null) {
            example.and().andBetween("gmtCreate", attendanceDedQuery.getGmtCreateStart(),
                    attendanceDedQuery.getGmtCreateEnd());
        }
        if (attendanceDedQuery.getCreateUserId() != null) {
            example.and().andLike("createUserId", "%" + attendanceDedQuery.getCreateUserId() + "%");
        }
        if (attendanceDedQuery.getGmtModifiedStart() != null &&
                attendanceDedQuery.getGmtModifiedEnd() != null) {
            example.and().andBetween("gmtModified", attendanceDedQuery.getGmtModifiedStart(),
                    attendanceDedQuery.getGmtModifiedEnd());
        }
        if (attendanceDedQuery.getModifiedUserId() != null) {
            example.and().andLike("modifiedUserId", "%" + attendanceDedQuery.getModifiedUserId() + "%");
        }
        // 排序
        ExampleKit.setExampleOrder(example, attendanceDedQuery.getOrders());
        return example;
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public Boolean attendanceDedCount(TokenUser tokenUser, AttendanceMonthlyAddDTO attendanceMonthlyAddDTO) {
        //获取员工列表（已初始化员工秘钥、社保相关、薪资）
        EmpInfoDO empInfoDO = new EmpInfoDO();
        empInfoDO.setValid(true);
        empInfoDO.setCompanyId(attendanceMonthlyAddDTO.getCompanyId());
        List<EmpInfoDO> empInfoDOList = empInfoService.listWithSalary(empInfoDO, tokenUser.getSiteId());
        if (CollectionUtils.isEmpty(empInfoDOList)) {
            return false;
        }

        HrLogKit.logForSelect("获取员工打卡考勤状态记录：" + attendanceMonthlyAddDTO.getYear() + "年" + attendanceMonthlyAddDTO.getMonth() + "月", "AttendPunchRecord", "0", tokenUser);
        //获取考勤状态列表
        Example example = new Example(AttendPunchRecordDO.class);
        example.and()
                .andEqualTo("companyId", attendanceMonthlyAddDTO.getCompanyId())
                .andEqualTo("siteId", tokenUser.getSiteId())
                .andEqualTo("yearly", attendanceMonthlyAddDTO.getYear())
                .andEqualTo("monthly", attendanceMonthlyAddDTO.getMonth());
//                .andCondition("DATE_FORMAT(punch_time ,'%Y-%m') = ", attendanceMonthlyAddDTO.getYear() + "-" + attendanceMonthlyAddDTO.getMonth());
        List<AttendPunchRecordDO> attendDailyStatusDOList = attendPunchRecordDAO.selectByExample(example);

        //获取扣款设置方案
//        AttendanceDedDO attendanceDedDOTmp = new AttendanceDedDO();
//        attendanceDedDOTmp.setStatus(true);
//        List<AttendanceDedDO> attendanceDedDOList = listWithItem(attendanceDedDOTmp, tokenUser.getSiteId());
        AttendanceDedProgDO attendanceDedProgDOTmp = new AttendanceDedProgDO();
        attendanceDedProgDOTmp.setValid(true);
        attendanceDedProgDOTmp.setSiteId(tokenUser.getSiteId());
        attendanceDedProgDOTmp.setCompanyId(attendanceMonthlyAddDTO.getCompanyId());
        List<AttendanceDedProgDO> attendanceDedProgDOList = progListWithItem(attendanceDedProgDOTmp, tokenUser.getSiteId());

        //获取扣款方案列表
//        List<ApplyToProgEmpeeInfoDTO> applyToProgEmpeeInfoDTOList = applyToProgService.getApplyToProgEmployee(ProgTypeEnum.ATTENDANCE_DED.getValue(), tokenUser.getSiteId());

        //当前时间
        Date now = DateKit.getToday();
        //员工考勤月统计列表
        List<AttendanceMonthlyDO> attendanceMonthlyDOList = new ArrayList<>();

        //删除相同年月的月考勤记录
        AttendanceMonthlyDO attendanceMonthlyDOParam = new AttendanceMonthlyDO();
        attendanceMonthlyDOParam.setYear(attendanceMonthlyAddDTO.getYear());
        attendanceMonthlyDOParam.setMonth(attendanceMonthlyAddDTO.getMonth());
        attendanceMonthlyDOParam.setCompanyId(attendanceMonthlyAddDTO.getCompanyId());
        attendanceMonthlyDOParam.setSiteId(tokenUser.getSiteId());
        attendanceMonthlyDao.delete(attendanceMonthlyDOParam);
        HrLogKit.logForDelete("删除月考勤记录", "deleteAttendanceMonthly", attendanceMonthlyDOParam.getId(), tokenUser);
        //考勤扣款方案列表
        for (AttendanceDedProgDO attendanceDedProgDO : attendanceDedProgDOList) {
            //获取考勤方案下员工列表
            ApplyToProgEmpeeInfoDTO applyToProgEmpeeInfoDTO = applyToProgService.getApplyToProgEmployeeByBusProgId(attendanceDedProgDO.getId(), tokenUser.getSiteId(), attendanceMonthlyAddDTO.getCompanyId());
            if (Objects.isNull(applyToProgEmpeeInfoDTO)) {
                continue;
            }
            //适用方案员工ID列表
            List<String> empIdList = applyToProgEmpeeInfoDTO.getEmpInfoDOList().stream().map(item -> item.getId()).collect(Collectors.toList());
            empInfoDOList = empInfoDOList.stream().filter(item -> empIdList.contains(item.getId())).collect(Collectors.toList());
            for (EmpInfoDO empInfoDOTmp : empInfoDOList) {
                //迟到扣款
                Integer dedLate = 0;
                //早退扣款
                Integer dedLeave = 0;
                //旷工扣款
                Integer dedAbsenteeism = 0;
                //补签扣款
                Integer dedSupplement = 0;
                //综合扣款
                Integer dedOverall = 0;

                //旷工扣款日薪倍数
                Integer dedAbsenteeismMul = 0;

                //当前员工的考勤记录
                List<AttendPunchRecordDO> attendDailyStatusDOListTmp = attendDailyStatusDOList.stream().filter(item -> item.getEmpInfoId().equals(empInfoDOTmp.getId())).collect(Collectors.toList());

                //当前员工的各个异常考勤统计
                Long timesLateOverAll = attendDailyStatusDOListTmp.stream().filter(item -> AttendStatus.LATE.getValue().equals(item.getPunchStatus()) && item.getMinute() != null).count();
                Long timesLeaveOverAll = attendDailyStatusDOListTmp.stream().filter(item -> AttendStatus.EARLY.getValue().equals(item.getPunchStatus()) && item.getMinute() != null).count();
                Long timesAbsenteeismOverAll = attendDailyStatusDOListTmp.stream().filter(item -> AttendStatus.ABSENTEEISM.getValue().equals(item.getPunchStatus())).count();
                Long timesSupplementOverAll = attendDailyStatusDOListTmp.stream().filter(item -> item.getIsMakeUp()).count();
                Long timesOverall = timesLateOverAll + timesLeaveOverAll + timesAbsenteeismOverAll + timesSupplementOverAll;
                Integer minutesSumLate = attendDailyStatusDOListTmp.stream().filter(item -> AttendStatus.LATE.getValue().equals(item.getPunchStatus())).map(AttendPunchRecordDO::getMinute).reduce(0, Integer::sum);
                Integer minutesSumLeave = attendDailyStatusDOListTmp.stream().filter(item -> AttendStatus.EARLY.getValue().equals(item.getPunchStatus())).map(AttendPunchRecordDO::getMinute).reduce(0, Integer::sum);

                //各个扣款设置项（因为考勤打卡功能修改了枚举状态，数据库未变更，则数值对应不上，attendanceDed的dedType需要变更去对应枚举!!!）
                for (AttendanceDedDO attendanceDedDO : attendanceDedProgDO.getAttendanceDedDOList()) {
                    switch (AttendStatus.find(Integer.valueOf(attendanceDedDO.getDedType().equals("5") ? "6" : attendanceDedDO.getDedType()) + 1)) {
                        case LATE:
                            //迟到扣款
                            if (attendanceDedDO.getType() == 1) {
                                //按阶梯
                                List<AttendanceDedItemDO> attendanceDedItemDOList = attendanceDedDO.getAttendanceDedItemDOList();
                                //当前规则上一时间节点
                                Integer timeCurrent = 0;
                                for (AttendanceDedItemDO attendanceDedItemDO : attendanceDedItemDOList) {
                                    //迟到总次数
                                    Long timesLate = 0L;
                                    if (attendanceDedItemDO.getTimeOperator() == 1) {
                                        Integer finalTimeCurrent = timeCurrent;
                                        timesLate = attendDailyStatusDOListTmp.stream().filter(item -> AttendStatus.LATE.getValue().equals(item.getPunchStatus()) && item.getMinute() != null).filter(item -> item.getMinute() <= attendanceDedItemDO.getTimeValue() && item.getMinute() > finalTimeCurrent).count();
                                    } else if (attendanceDedItemDO.getTimeOperator() == 2) {
                                        timesLate = attendDailyStatusDOListTmp.stream().filter(item -> AttendStatus.LATE.getValue().equals(item.getPunchStatus()) && item.getMinute() != null).filter(item -> item.getMinute() > attendanceDedItemDO.getTimeValue()).count();
                                    }
                                    timeCurrent = attendanceDedItemDO.getTimeValue();
                                    //当前规则剩余次数
                                    Integer timesCurrent = 0;
                                    List<AttendanceDedParamDO> attendanceDedParamList = attendanceDedItemDO.getAttendanceDedParamDOList();
                                    for (AttendanceDedParamDO attendanceDedParamDO : attendanceDedParamList) {
                                        if (timesLate > 0) {
                                            timesCurrent = attendanceDedParamDO.getTimesValue() - timesCurrent;
                                            if (attendanceDedParamDO.getTimesOperator() == 1) {
                                                if (attendanceDedParamDO.getDedType() == 1) {
                                                    // 固定金额扣款
                                                    if (timesLate >= timesCurrent) {
                                                        //剩余总次数大于等于规则次数
                                                        dedLate = dedLate + (attendanceDedParamDO.getDedAmount() * timesCurrent);
                                                    } else {
                                                        //剩余总次数小于规则次数
                                                        dedLate = dedLate + (attendanceDedParamDO.getDedAmount() * timesLate.intValue());
                                                    }
                                                } else {
                                                    if (timesLate >= timesCurrent) {
                                                        //剩余总次数大于等于规则次数
                                                        // 旷工天数增加
                                                        timesAbsenteeismOverAll += (timesCurrent * attendanceDedParamDO.getAbsenteeismValue().intValue());
                                                    } else {
                                                        //剩余总次数小于规则次数
                                                        // 旷工天数增加
                                                        timesAbsenteeismOverAll += (timesLate.intValue() * attendanceDedParamDO.getAbsenteeismValue().intValue());
                                                    }
                                                }
                                                timesLate = timesLate - timesCurrent;
                                            } else if (attendanceDedParamDO.getTimesOperator() == 2) {
                                                if (attendanceDedParamDO.getDedType() == 1) {
                                                    // 固定金额扣款
                                                    //剩余总次数大于规则最大次数
                                                    dedLate = dedLate + (timesLate.intValue() * (attendanceDedParamDO.getDedAmount() == null ? 0 : attendanceDedParamDO.getDedAmount()));
                                                } else {
                                                    // 旷工天数增加
                                                    timesAbsenteeismOverAll += (timesLate.intValue() * attendanceDedParamDO.getAbsenteeismValue().intValue());
                                                }
                                            }
                                        }
                                    }


                                }
                            } else if (attendanceDedDO.getType() == 2) {
                                //按每分钟
//                            Integer minutesSum = attendanceStatusDOListTmp.stream().filter(item -> item.getStatus() == 3).map(AttendanceStatusDO::getMinutes).reduce(0, Integer::sum);
//                            Long timesLate = attendanceStatusDOListTmp.stream().filter(item -> item.getStatus() == 3).count();
//                            System.out.println(empInfoDOTmp.getName() + "迟到总分钟数：" + minutesSum);
//                            System.out.println(empInfoDOTmp.getName() + "迟到次数：" + timesLate);
                                //月迟到扣款金额
                                dedLate = dedLate + (minutesSumLate * attendanceDedDO.getAmountMinute());

                            }
                            break;
                        case EARLY:
                            //早退扣款
                            if (attendanceDedDO.getType() == 1) {
                                //按阶梯
                                List<AttendanceDedItemDO> attendanceDedItemDOList = attendanceDedDO.getAttendanceDedItemDOList();
                                //当前规则上一时间节点
                                Integer timeCurrent = 0;
                                for (AttendanceDedItemDO attendanceDedItemDO : attendanceDedItemDOList) {
                                    //早退总次数
                                    Long timesLeave = 0L;
                                    if (attendanceDedItemDO.getTimeOperator() == 1) {
                                        Integer finalTimeCurrent = timeCurrent;
                                        timesLeave = attendDailyStatusDOListTmp.stream().filter(item -> AttendStatus.EARLY.getValue().equals(item.getPunchStatus()) && item.getMinute() != null).filter(item -> item.getMinute() <= attendanceDedItemDO.getTimeValue() && item.getMinute() > finalTimeCurrent).count();
                                    } else if (attendanceDedItemDO.getTimeOperator() == 2) {
                                        timesLeave = attendDailyStatusDOListTmp.stream().filter(item -> AttendStatus.EARLY.getValue().equals(item.getPunchStatus()) && item.getMinute() != null).filter(item -> item.getMinute() > attendanceDedItemDO.getTimeValue()).count();
                                    }
                                    timeCurrent = attendanceDedItemDO.getTimeValue();
                                    //当前规则剩余次数
                                    Integer timesCurrent = 0;
                                    List<AttendanceDedParamDO> attendanceDedParamList = attendanceDedItemDO.getAttendanceDedParamDOList();
                                    for (AttendanceDedParamDO attendanceDedParamDO : attendanceDedParamList) {
                                        if (timesLeave > 0) {
                                            timesCurrent = attendanceDedParamDO.getTimesValue() - timesCurrent;
                                            if (attendanceDedParamDO.getTimesOperator() == 1) {
                                                if (attendanceDedParamDO.getDedType() == 1) {
                                                    // 固定金额扣款
                                                    if (timesLeave >= timesCurrent) {
                                                        //剩余总次数大于等于规则次数
                                                        dedLeave = dedLeave + (attendanceDedParamDO.getDedAmount() * timesCurrent);
                                                    } else {
                                                        //剩余总次数小于规则次数
                                                        dedLeave = dedLeave + (attendanceDedParamDO.getDedAmount() * timesLeave.intValue());
                                                    }
                                                } else {
                                                    if (timesLeave >= timesCurrent) {
                                                        //剩余总次数大于等于规则次数
                                                        // 旷工天数增加
                                                        timesAbsenteeismOverAll += (timesCurrent * attendanceDedParamDO.getAbsenteeismValue().intValue());
                                                    } else {
                                                        //剩余总次数小于规则次数
                                                        // 旷工天数增加
                                                        timesAbsenteeismOverAll += (timesLeave.intValue() * attendanceDedParamDO.getAbsenteeismValue().intValue());
                                                    }
                                                }
                                                timesLeave = timesLeave - timesCurrent;
                                            } else if (attendanceDedParamDO.getTimesOperator() == 2) {
                                                if (attendanceDedParamDO.getDedType() == 1) {
                                                    // 固定金额扣款
                                                    //剩余总次数大于规则最大次数
                                                    dedLeave = dedLeave + (timesLeave.intValue() * attendanceDedParamDO.getDedAmount());
                                                } else {
                                                    // 旷工天数增加
                                                    timesAbsenteeismOverAll += (timesLeave.intValue() * attendanceDedParamDO.getAbsenteeismValue().intValue());
                                                }
                                            }
                                        }
                                    }


                                }
                            } else if (attendanceDedDO.getType() == 2) {
                                //按每分钟
//                            Integer minutesSum = attendanceStatusDOListTmp.stream().filter(item -> item.getStatus() == 4).map(AttendanceStatusDO::getMinutes).reduce(0, Integer::sum);
//                            Long timesLate = attendanceStatusDOListTmp.stream().filter(item -> item.getStatus() == 4).count();
//                            System.out.println(empInfoDOTmp.getName() + "早退总分钟数：" + minutesSum);
//                            System.out.println(empInfoDOTmp.getName() + "早退次数：" + timesLate);
                                //月迟到扣款金额
                                dedLeave = dedLeave + (minutesSumLeave * attendanceDedDO.getAmountMinute());

                            }
                            break;
                        case ABSENTEEISM:
//                            //旷工扣款
//                            Integer salaryBasic = empInfoDOTmp.getSalaryBasic();
//                            Integer salaryByDay = new BigDecimal(salaryBasic).divide(HrConstants.MONTH_WORK_DAYS, ROUND_HALF_DOWN).setScale(2,BigDecimal.ROUND_DOWN).intValue();
//                            //旷工总次数
//                            Long timesAbsenteeism = 0L;
//                            timesAbsenteeism = attendDailyStatusDOListTmp.stream().filter(item -> AttendStatus.ABSENTEEISM.getValue().equals(item.getPunchStatus())).count();
//                            dedAbsenteeism = dedAbsenteeism + (salaryByDay * timesAbsenteeism.intValue() * (attendanceDedDO.getAmountAbsenteeism() == null ? 0 : attendanceDedDO.getAmountAbsenteeism()));
                            //旷工扣款日薪倍数
                            dedAbsenteeismMul = attendanceDedDO.getAmountAbsenteeism() == null ? 0 : attendanceDedDO.getAmountAbsenteeism();

                            break;
                        case SUPPLEMENT:
                            //补签扣款
                            List<AttendanceDedItemDO> attendanceDedItemDOList = attendanceDedDO.getAttendanceDedItemDOList();
                            if (attendanceDedItemDOList != null && attendanceDedItemDOList.size() > 0) {
                                AttendanceDedItemDO attendanceDedItemDO = attendanceDedItemDOList.get(0);
                                //补签总次数
                                Long timesSupplement = 0L;
                                timesSupplement = attendDailyStatusDOListTmp.stream().filter(item -> AttendStatus.SUPPLEMENT.getValue().equals(item.getPunchStatus())).count();
                                //当前规则剩余次数
                                Integer timesCurrent = 0;
                                List<AttendanceDedParamDO> attendanceDedParamList = attendanceDedItemDO.getAttendanceDedParamDOList();
                                for (AttendanceDedParamDO attendanceDedParamDO : attendanceDedParamList) {
                                    if (timesSupplement > 0) {
                                        timesCurrent = attendanceDedParamDO.getTimesValue() - timesCurrent;
                                        if (attendanceDedParamDO.getTimesOperator() == 1) {
                                            if (timesSupplement >= timesCurrent) {
                                                //剩余总次数大于等于规则次数
                                                dedSupplement = dedSupplement + (timesCurrent * attendanceDedParamDO.getDedAmount());
                                            } else {
                                                //剩余总次数小于规则次数
                                                dedSupplement = dedSupplement + (timesSupplement.intValue() * attendanceDedParamDO.getDedAmount());
                                            }
                                            timesSupplement = timesSupplement - timesCurrent;
                                        } else if (attendanceDedParamDO.getTimesOperator() == 2) {
                                            //剩余总次数大于规则最大次数
                                            dedSupplement = dedSupplement + (timesSupplement.intValue() * attendanceDedParamDO.getDedAmount());
                                        }
                                    }
                                }


                            }
                            break;
                        case OVERALL:
                            //综合扣款
                            List<AttendanceDedItemDO> attendanceDedItemDOListOverAll = attendanceDedDO.getAttendanceDedItemDOList();
                            if (attendanceDedItemDOListOverAll != null && attendanceDedItemDOListOverAll.size() > 0) {
                                AttendanceDedItemDO attendanceDedItemDO = attendanceDedItemDOListOverAll.get(0);
                                //综合总次数
//                                Long timesOverAllNow = timesOverall;
                                Long timesOverAllNow = 0L;
                                String[] overallRangeArray = StringUtils.isNotBlank(attendanceDedDO.getOverallRange()) ? attendanceDedDO.getOverallRange().split(",") : null;
                                for (String str : overallRangeArray) {
                                    switch (str) {
                                        case "lateTimes":
                                            timesOverAllNow += timesLateOverAll;
                                            break;
                                        case "leaveTimes":
                                            timesOverAllNow += timesLeaveOverAll;
                                            break;
                                        case "absenteeismTimes":
                                            timesOverAllNow += timesAbsenteeismOverAll;
                                            break;
                                        case "supplementTimes":
                                            timesOverAllNow += timesSupplementOverAll;
                                            break;
                                    }
                                }

                                //当前规则剩余次数
                                Integer timesCurrent = 0;
                                List<AttendanceDedParamDO> attendanceDedParamList = attendanceDedItemDO.getAttendanceDedParamDOList();
                                for (AttendanceDedParamDO attendanceDedParamDO : attendanceDedParamList) {
                                    if (timesOverAllNow > 0) {
                                        timesCurrent = attendanceDedParamDO.getTimesValue() - timesCurrent;
                                        if (attendanceDedParamDO.getTimesOperator() == 1) {
                                            if (timesOverAllNow >= timesCurrent) {
                                                //剩余总次数大于等于规则次数
                                                dedOverall = dedOverall + (timesCurrent * attendanceDedParamDO.getDedAmount());
                                            } else {
                                                //剩余总次数小于规则次数
                                                dedOverall = dedOverall + (timesOverAllNow.intValue() * attendanceDedParamDO.getDedAmount());
                                            }
                                            timesOverAllNow = timesOverAllNow - timesCurrent;
                                        } else if (attendanceDedParamDO.getTimesOperator() == 2) {
                                            //剩余总次数大于规则最大次数
                                            dedOverall = dedOverall + (timesOverAllNow.intValue() * attendanceDedParamDO.getDedAmount());
                                        }
                                    }
                                }


                            }
                            break;
                    }
                }

                // 旷工扣款（//TODO 每日：21.75）
                Integer salaryBasic = empInfoDOTmp.getSalaryBasic();
                Integer salaryByDay = new BigDecimal(salaryBasic).divide(HrConstants.MONTH_WORK_DAYS, ROUND_HALF_DOWN).setScale(2, BigDecimal.ROUND_DOWN).intValue();
                // 日薪 * 旷工总次数 * 旷工扣款倍数
                dedAbsenteeism = dedAbsenteeism + (salaryByDay * timesAbsenteeismOverAll.intValue() * dedAbsenteeismMul);

                System.out.println("迟到扣款金额：" + dedLate);
                System.out.println("早退扣款金额：" + dedLeave);
                System.out.println("旷工扣款金额：" + dedAbsenteeism);
                System.out.println("补签扣款金额：" + dedSupplement);
                System.out.println("综合扣款金额：" + dedOverall);
                System.out.println("迟到总次数：" + timesLateOverAll);
                System.out.println("早退总次数：" + timesLeaveOverAll);
                System.out.println("旷工总次数：" + timesAbsenteeismOverAll);
                System.out.println("补签总次数：" + timesSupplementOverAll);
                System.out.println("综合总次数：" + timesOverall);
                System.out.println("迟到总分钟数：" + minutesSumLate);
                System.out.println("早退总分钟数：" + minutesSumLeave);

                //员工考勤月统计添加记录
                AttendanceMonthlyDO attendanceMonthlyDO = new AttendanceMonthlyDO();
                BeanUtils.copyProperties(attendanceMonthlyDOParam, attendanceMonthlyDO);
                attendanceMonthlyDO.setEmpId(empInfoDOTmp.getId());
                attendanceMonthlyDO.setNumber(empInfoDOTmp.getNumber());
                attendanceMonthlyDO.setLateTimes(timesLateOverAll.intValue());
                attendanceMonthlyDO.setLateDed(dedLate);
                attendanceMonthlyDO.setLateMinutes(minutesSumLate);
                attendanceMonthlyDO.setLeaveTimes(timesLeaveOverAll.intValue());
                attendanceMonthlyDO.setLeaveDed(dedLeave);
                attendanceMonthlyDO.setLeaveMinutes(minutesSumLeave);
                attendanceMonthlyDO.setAbsenteeismTimes(timesAbsenteeismOverAll.intValue());
                attendanceMonthlyDO.setAbsenteeismDed(dedAbsenteeism);
                attendanceMonthlyDO.setSupplementTimes(timesSupplementOverAll.intValue());
                attendanceMonthlyDO.setSupplementDed(dedSupplement);
                attendanceMonthlyDO.setOverallTimes(timesOverall.intValue());
                attendanceMonthlyDO.setOverallDed(dedOverall);
                attendanceMonthlyDO.setSocDed(0);
                attendanceMonthlyDO.setPfDed(0);
                attendanceMonthlyDO.setPersonTaxDed(0);
                attendanceMonthlyDO.setTeamCommission(0);
                attendanceMonthlyDO.setBusinessCommission(0);
                attendanceMonthlyDO.setOvertimePay(0);
                attendanceMonthlyDO.setSubsidy(0);
                attendanceMonthlyDO.setValid(true);
                attendanceMonthlyDO.setCreateUserId(tokenUser.getUserId());
                attendanceMonthlyDO.setGmtCreate(now);
                attendanceMonthlyDO.setModifiedUserId(tokenUser.getUserId());
                attendanceMonthlyDO.setGmtModified(now);
                attendanceMonthlyDOList.add(attendanceMonthlyDO);
            }
        }
        HrLogKit.logForSave("根据考勤扣款设置规则计算并生成考勤月统计：" + attendanceMonthlyAddDTO.getYear() + "年" + attendanceMonthlyAddDTO.getMonth() + "月", "attendanceMonthly", "0", tokenUser);
        if (!CollectionUtils.isEmpty(attendanceMonthlyDOList)) {
            attendanceMonthlyDao.insertList(attendanceMonthlyDOList);
        }
        HrLogKit.logForSave("批量新增员工考勤月统计", "insertListAttendanceMonthly", attendanceMonthlyDOList
                .parallelStream().map(BaseDO::getId).collect(Collectors.joining(",", "[", "]")), tokenUser);
        return true;
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public List<AttendanceDedDO> listWithItem(AttendanceDedDO attendanceDedDO, String siteId) {
        return attendanceDedDAO.listWithItem(attendanceDedDO, siteId);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public List<AttendanceDedProgDO> progListWithItem(AttendanceDedProgDO attendanceDedProgDO, String siteId) {
        return attendanceDedDAO.progListWithItem(attendanceDedProgDO, siteId);
    }


}
